package me.w70.bot.scripting;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;

import me.w70.bot.Bot;

public class ScriptLoader {

	private HashMap<String, Script> loadedScripts = new HashMap<String, Script>();

	private HashMap<String, Random> loadedRandoms = new HashMap<String, Random>();

	private HashMap<String, Script> loadedPassiveScripts = new HashMap<String, Script>();

	private HashMap<String, Class> loadedRandomClasses = new HashMap<String, Class>();

	private HashMap<String, Class> loadedScriptClasses = new HashMap<String, Class>();

	private HashMap<String, Class> loadedPassiveClasses = new HashMap<String, Class>();

	private HashMap<String, Script> loadedScriptIdle = new HashMap<String, Script>();

	public HashMap<String, Script> getLoadedScripts() {
		return loadedScripts;
	}

	public HashMap<String, Script> getAllLoadedScripts() {
		return loadedScriptIdle;
	}

	public HashMap<String, Random> getLoadedRandoms() {
		return loadedRandoms;
	}

	public Class findScript(String name) {
		if (loadedScriptClasses.containsKey(name)) {
			return loadedScriptClasses.get(name);
		}

		ClassLoader cl = null;
		try {
			cl = new URLClassLoader(new URL[] { new URL(
					"file:./scripts/") });
		} catch (MalformedURLException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		Class<?> scriptClass = null;
		try {
			scriptClass = cl.loadClass(name.replace(".class", ""));
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return scriptClass;

	}

	public Class findPassiveScript(String name) {
		if (loadedPassiveClasses.containsKey(name)) {
			return loadedPassiveClasses.get(name);
		}

		ClassLoader cl = null;
		try {
			cl = new URLClassLoader(new URL[] { new URL(
					"file:./passive/") });
		} catch (MalformedURLException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		Class<?> scriptClass = null;
		try {
			scriptClass = cl.loadClass(name.replace(".class", ""));
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return scriptClass;

	}

	public Class findRandom(String name) {
		if (loadedRandomClasses.containsKey(name)) {
			return loadedRandomClasses.get(name);
		}
		ClassLoader cl = null;
		try {
			cl = new URLClassLoader(new URL[] { new URL(
					"file:./randoms/") });
		} catch (MalformedURLException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		Class<?> scriptClass = null;
		try {
			scriptClass = cl.loadClass(name.replace(".class", ""));
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return scriptClass;
	}

	public void loadRandoms() {
		File folder = new File(Bot.RANDOM_DIR);
		File[] listOfFiles = folder.listFiles();

		for (int i = 0; i < listOfFiles.length; i++) {
			if (listOfFiles[i].isFile()) {
				if (listOfFiles[i].getName().substring(
						listOfFiles[i].getName().length() - 6,
						listOfFiles[i].getName().length()).equals(".class")) {
					if (loadedRandomClasses.containsKey(listOfFiles[i]
							.getName().substring(0,
									listOfFiles[i].getName().length() - 6))) {

					} else {
						loadedRandomClasses
								.put(listOfFiles[i].getName().substring(0,
										listOfFiles[i].getName().length() - 6),
										findRandom(listOfFiles[i].getName()
												.substring(
														0,
														listOfFiles[i]
																.getName()
																.length() - 6)));
						loadRandom(listOfFiles[i].getName().substring(0,
								listOfFiles[i].getName().length() - 6));
					}
				}
			} else if (listOfFiles[i].isDirectory()) {
			}
		}
	}

	public void loadScripts() {
		File folder = new File(Bot.SCRIPT_DIR);
		File[] listOfFiles = folder.listFiles();

		for (int i = 0; i < listOfFiles.length; i++) {
			if (listOfFiles[i].isFile()) {
				if (listOfFiles[i].getName().substring(
						listOfFiles[i].getName().length() - 6,
						listOfFiles[i].getName().length()).equals(".class")) {
					loadedScriptClasses.put(listOfFiles[i].getName().substring(
							0, listOfFiles[i].getName().length() - 6),
							findScript(listOfFiles[i].getName().substring(0,
									listOfFiles[i].getName().length() - 6)));
					loadScript(listOfFiles[i].getName().substring(0,
							listOfFiles[i].getName().length() - 6));
				}
			} else if (listOfFiles[i].isDirectory()) {
			}
		}
	}

	public void loadPassive() {
		File folder = new File(Bot.PASSIVE_DIR);
		File[] listOfFiles = folder.listFiles();

		for (int i = 0; i < listOfFiles.length; i++) {
			if (listOfFiles[i].isFile()) {
				if (listOfFiles[i].getName().substring(
						listOfFiles[i].getName().length() - 6,
						listOfFiles[i].getName().length()).equals(".class")) {
					loadedPassiveClasses
							.put(listOfFiles[i].getName().substring(0,
									listOfFiles[i].getName().length() - 6),
									findPassiveScript(listOfFiles[i].getName()
											.substring(
													0,
													listOfFiles[i].getName()
															.length() - 6)));
					loadPassiveScript(listOfFiles[i].getName().substring(0,
							listOfFiles[i].getName().length() - 6));
				}
			} else if (listOfFiles[i].isDirectory()) {
			}
		}
	}

	public void loadScript(String name) {
		Class c;
		c = loadedScriptClasses.get(name);

		try {
			Script s = (Script) c.newInstance();
			loadedScriptIdle.put(s.getScriptName(), s);
			Bot.addMessage(this.getClass(), "Loaded script '"
					+ s.getScriptName() + "'");
		} catch (Exception e) {
			// e.printStackTrace();
		}
	}

	public void loadPassiveScript(String name) {
		Class c;
		c = loadedPassiveClasses.get(name);

		try {
			Script s = (Script) c.newInstance();
			s.onLoad();
			s.running = true;

			if (!s.hasRun()) {
				s.start();
			}

			loadedPassiveScripts.put(s.getScriptName(), s);
			Bot.addMessage(this.getClass(), "Loaded script '"
					+ s.getScriptName() + "'");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void loadRandom(String name) {
		Class c;
		c = loadedRandomClasses.get(name);

		try {

			Random r = (Random) c.newInstance();
			r.start();
			loadedRandoms.put(r.getScriptName(), r);
			/*
			 * Bot.addMessage(this.getClass(), "Loaded random '" +
			 * r.getScriptName() + "'");
			 */
		} catch (Exception e) {
		}
	}

	public void runScript(String name) {

		Script s = loadedScriptIdle.get(name);
		if (s.isRunning()) {
			Bot.addMessage(this.getClass(), "Script '" + name
					+ "' is already running!");
			return;
		}
		try {
			s.gui = new GUIBuilder(s);
			s.onLoad();
			if (!s.usesGUI) {

				s.running = true;
				if (!s.hasRun()) {
					s.start();
				}
			}
			loadedScripts.put(name, s);
			if (!s.getScriptCategory().equalsIgnoreCase("debug")) {
				Bot.gui.allowInputBtn.setText("Allow Input");
				Bot.gui.allowInputBtn.setActionCommand("allowInput");
				Bot.allowInput = false;

				Bot
						.addMessage(this.getClass(), "Started script '" + name
								+ "'");
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	boolean paused = false;

	public void togglePauseScripts() {
		paused = !paused;
		for (Script s : loadedScripts.values()) {
			if (!s.getScriptCategory().equalsIgnoreCase("debug")) {
				s.pause(!paused);
			}
		}
		Bot.addMessage(this.getClass(), (paused == true) ? "Paused script(s)"
				: "Resumed script(s)");

	}

	public void stopScript(String name) {
		try {
			for (Script s : loadedScripts.values()) {
				if (s.isRunning() && s.getScriptName().equals(name)) {
					s.running = false;
					s.onEnd();
					loadedScripts.remove(name);
				}
			}
		} catch (Exception e) {

		}
	}

	public void stopScripts() {
		for (Script s : loadedScripts.values()) {
			if (s.isRunning()) {

				s.running = false;
				s.onEnd();
				Bot.addMessage(this.getClass(), "Stopped script '"
						+ s.getScriptName() + "'");
			}

		}
	}

}
